﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using WyUnity.Data.DataAccess;
using System.Linq.Expressions;
using WyUnity.Data.TableMapper;
using WyUnity.Utility;
using System.Linq;

namespace WyUnity.Data.Query
{
    /*
	[Serializable]
	public class Where<T> : Where
	{
		public Where(Expression<Func<T, object>> propertyExpression, SqlCompareOperation condition, object value)
		{
			var ebody = propertyExpression.Body;
			if (ebody is UnaryExpression)
			{
				var bbody = ebody as UnaryExpression;
				if (bbody.NodeType == ExpressionType.Convert)
				{
					ebody = bbody.Operand;
				}
				else
				{
					ebody = null;
				}
			}
			var body = ebody as System.Linq.Expressions.MemberExpression;
			if (body == null) throw new NotSupportedException("在定义Where条件时，只能使用返回单一属性的Lambda表达式");
			//Log.Default.Debug(body.Member.Name);

			_field = GetMapField(body);
			_condition = condition;
			_value = value;
		}
		public Where(Expression<Func<T, ValueType>> propertyExpression, SqlCompareOperation condition, object value)
		{
			var ebody = propertyExpression.Body;
			if (ebody is UnaryExpression)
			{
				var bbody = ebody as UnaryExpression;
				if (bbody.NodeType == ExpressionType.Convert)
				{
					ebody = bbody.Operand;
				}
				else
				{
					ebody = null;
				}
			}
			var body = ebody as System.Linq.Expressions.MemberExpression;
			if (body == null) throw new NotSupportedException("在定义Where条件时，只能使用返回单一属性的Lambda表达式");
			//Log.Default.Debug(body.Member.Name);

			_field = GetMapField(body);
			_condition = condition;
			_value = value;
		}
		//[Obsolete()]
		//public Where(Expression<Func<T, bool>> propertyExpression)
		//{
		//    var body = propertyExpression.Body as System.Linq.Expressions.BinaryExpression;
		//    var left = body.Left as MemberExpression;
		//    var operate = body.NodeType;
		//    var right = body.Right as ConstantExpression;

		//    if (left == null || right == null) throw new NotSupportedException("目前只能支持简单的条件表达式");

		//    _field = GetMapField(left);
		//    _condition = GetSqlCompareOperation(operate);
		//    _value = right.Value;

		//}
		private static string GetMapField(MemberExpression exp)
		{
			var member = GetPropMember(exp);
			var map = member.GetSingleAttribute<MapAttribute>();
			if (map == null || string.IsNullOrEmpty(map.Name)) return member.Name;
			return map.Name;
		}
		private static MemberInfo GetPropMember(MemberExpression exp)
		{
			return exp.Member;
		}
		private static SqlCompareOperation GetSqlCompareOperation(ExpressionType etype)
		{
			switch (etype)
			{
				case ExpressionType.Equal:
					return SqlCompareOperation.Equal;
				case ExpressionType.GreaterThan:
					return SqlCompareOperation.Greater;
				case ExpressionType.GreaterThanOrEqual:
					return SqlCompareOperation.GreaterOrEqual;
				case ExpressionType.LessThan:
					return SqlCompareOperation.Less;
				case ExpressionType.LessThanOrEqual:
					return SqlCompareOperation.LessOrEqual;
				case ExpressionType.NotEqual:
					return SqlCompareOperation.NotEqual;
				default:
					throw new NotSupportedException("不支持该表达式:" + etype.ToString());
			}
		}
	}
    */
	[Serializable]
	public class Where : WhereClip, IClip
	{
		protected string _field;
		protected SqlCompareOperation _condition;
		protected object _value;

		public Where(string field, SqlCompareOperation condition, object value)
		{
			_field = field;
			_condition = condition;
			_value = value;
		}
		public Where(string field, object value)
			: this(field, SqlCompareOperation.Equal, value)
		{
		}
		internal protected Where() { }

		public override WhereClip And(WhereClip andClip)
		{
			var rlt = new WhereGroup(this, WhereConnect.And);
			rlt.Add(andClip, WhereConnect.And);
			return rlt;
		}

		public override WhereClip Or(WhereClip orClip)
		{
			var rlt = new WhereGroup(this, WhereConnect.Or);
			rlt.Add(orClip, WhereConnect.Or);
			return rlt;
		}
		protected string OperatorToString(SqlCompareOperation o)
		{
			switch (o)
			{
				case SqlCompareOperation.Equal:
					return "=";
				case SqlCompareOperation.Greater:
					return ">";
				case SqlCompareOperation.GreaterOrEqual:
					return ">=";
				case SqlCompareOperation.Less:
					return "<";
				case SqlCompareOperation.LessOrEqual:
					return "<=";
				case SqlCompareOperation.Like:
					return " like ";
				case SqlCompareOperation.NotEqual:
					return "<>";
				case SqlCompareOperation.In:
					return "In";
				case SqlCompareOperation.IsNull:
                    return " is null";
                case SqlCompareOperation.IsNotNull:
                    return " is not null";
				default:
					throw new NotImplementedException();
			}
		}
		public override string ToClip(ParameterProvider pp)
		{
			_parameters = pp;
			if (_condition == SqlCompareOperation.In)
			{
				var valuelist = _value as IEnumerable;
				if (valuelist == null)
					throw new DAException("In的值必须是数组类型");

				var plist = string.Empty;
				foreach (var v in valuelist)
				{
					var pname = pp.CreateOne(v);
					plist += "," + pname;
				}
				plist = plist.Substring(1);
				return string.Format("[{0}] in ({1})", _field, plist);
			}
			else if (_condition == SqlCompareOperation.IsNull)
			{
				return string.Format("[{0}] is null", _field);
			}
			else
			{
				var pname = pp.CreateOne(_value);
				return string.Format("[{0}]{1}{2}", _field, OperatorToString(_condition), pname);
			}
		}

		[NonSerialized]
        [System.Xml.Serialization.SoapIgnore]
		protected ParameterProvider _parameters;
        [System.Xml.Serialization.SoapIgnore]
		public override ParameterProvider Parameters
		{
			get
			{
				return _parameters;
			}
			protected set { }
		}
		public override string ToSqlClip(ISqlDialect dialect)
		{
			_parameters = new ParameterProvider(dialect, "W");
			return "Where " + ToClip(_parameters);
		}
		//public static WhereClip All()
		//{
		//	return new WhereAll();
		//}

		public override List<string> GetAllField()
		{
			return new List<string> { _field };
		}

	}
}